#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <algorithm>

using namespace std;

// forn : for ( i en [0,n) )
#define forn( i,n ) for ( int i=0; i<(int)(n); i++ )
// fornin : for ( i en [desde,hasta) )
#define fornin(i, desde, hasta) for ( int i=(desde); i<(int)(hasta); i++ )
// decl : Declara la variable v igual que c
#define decl(v, c) typeof(c) v = c
// forall : foreach( i in c)
#define forall(i, c) for(decl(i, c.begin()); i!=c.end(); ++i)
// forall : foreach( i,j in c) talque i != j
#define forallDist(i, j , c) for(decl(i, c.begin()); ((++i)--) != c.end(); i++) for(decl(j, ((++i)--)); j != c.end(); j++)

typedef pair<int, string > nodo;
typedef vector< nodo > recorridos;
typedef set< nodo > nodos;
typedef map< nodo, int > posiciones;
typedef pair<int, int> respuesta;
typedef vector< respuesta > respuestas;
typedef vector< bool > vbool;

char caracter_extra;
#define infinito 1000000
#define un_dia 1440

string int2string(int n){
    stringstream flujo;
    flujo << n;
    return flujo.str();
}

string minutos(int tiempo){
    int min = tiempo % 60;
    if(min > 9) {
        return int2string(min);
    } else {
        return "0"+ int2string(min);
	}
}

string horasFormated(int tiempo){
    int min = tiempo % 60;
    int h = (tiempo - min ) / 60;
    if(h > 9){
        return int2string(h);
    }else{
        return "0"+ int2string(h);
	}
}

string horasNoFormated(int tiempo){
    int min = tiempo % 60;
    int h = (tiempo - min) / 60;
    return int2string(h);
}

string tiempoFormated(int tiempo){
    return horasFormated(tiempo) + ":" + minutos(tiempo);
}

string tiempoNoFormated(int tiempo){
    return horasNoFormated(tiempo) + ":" + minutos(tiempo);
}

int posicionDe(int i, string s, posiciones &las_pos){
    return las_pos[nodo(i,s)];
}

void ResolverUnCaso(){
    int cant_recorridos = 0;
    int cant_estaciones = 0;
    int tiempo_actual = 0;
    int horas, minutos;

    string ciudad, desde, hasta;

    /** Levanto los datos de entrada **/
    cin >> cant_recorridos;

    recorridos los_recorridos[cant_recorridos];   // Un Diccionario de recorridos
    nodos los_nodos;                    // Todos los nodos ( un nodo es un par Ciudad Horario )
    posiciones las_posiciones;          // Algo que mapea Cada Nodo a un int (posicion en la matriz)
    vbool es_estacion_primera;          // Me fijo si es la primera estacion.

    int posicion_nodo = 0;
    forn(un_recorrido, cant_recorridos){ // Para cada recorrido
        cin >> cant_estaciones;
        tiempo_actual = 0;
        bool es_primera = true;
        forn(una_estacion, cant_estaciones) {// Para cada estacion en un recorrido
            cin >> horas >> caracter_extra >> minutos >> ciudad;
            int duracion_viaje = horas * 60 + minutos;
            tiempo_actual += duracion_viaje;  // Obtengo el tiempo actual de esta estacion.

            nodo un_nodo = nodo(tiempo_actual%un_dia, ciudad);         // Creo el nodo Ciudad Horario
            los_recorridos[un_recorrido].push_back(nodo(tiempo_actual, ciudad));   // Guardo esta ciudad en el recorrido.
            if(las_posiciones.find(un_nodo) == las_posiciones.end()){ // Si el nodo no existe!
                los_nodos.insert(un_nodo);  // Guardo el nodo
                las_posiciones[un_nodo] = posicion_nodo; // Guardo la posicion del nodo
                es_estacion_primera.assign(posicion_nodo, es_primera); // Guardo si es primera estacion
                es_primera = false;
                posicion_nodo++;
            }
        }
    }

    cin >> desde >> hasta; // Obtengo la el origen y destino.
    /** Fin levantar datos **/
    
    // Creo la matriz de aydacencia de los nodos y la inicalizo en infinito
    int cantidad_nodos = los_nodos.size();
    int matriz_ady[cantidad_nodos][cantidad_nodos];
    forn(x, cantidad_nodos) forn(y, cantidad_nodos) {
        matriz_ady[x][y] = infinito;
	}
    /** Inicializo la matriz de ady con el tiempo entre recorridos **/
    forn(un_recorrido, cant_recorridos){ // Para cada recorrido
        forall(una_estacion, los_recorridos[un_recorrido]){ // Para cada estacion
            decl(siguiente_estacion, ++una_estacion); // Busco la siguiente estacion
            if(siguiente_estacion!=los_recorridos[un_recorrido].end()){ // Si existe la siguiente estacion
                una_estacion--;
                int diferencia = siguiente_estacion->first - una_estacion->first;// Obtengo el tiempo entre una y otra
                int pos_una_estacion        = posicionDe(una_estacion->first % un_dia   , una_estacion->second, las_posiciones);
                int pos_siguiente_estacion  = posicionDe(siguiente_estacion->first % un_dia, siguiente_estacion->second, las_posiciones);
                matriz_ady[pos_una_estacion][pos_siguiente_estacion] = diferencia; // Modifico el tiempo entre las estaciones
            } else {
                break;
			}
        }
    }

    /** Inicializo la matriz de ady con el tiempo "muerto" en una misma ciudad **/
    forallDist(i,j, los_nodos){ // Para todo par de nodos
        if(i->second == j->second) {// Si es la misma ciudad
            int pos_i = las_posiciones[nodo(i->first, i->second)];
            int pos_j = las_posiciones[nodo(j->first, j->second)];
            int diferencia_i_a_j = (j->first - i->first ); // Obtengo el tiempo entre una y otra
            int diferencia_j_a_i = un_dia - (diferencia_i_a_j % un_dia);
            if(!es_estacion_primera[pos_i])  {                // A menos que sea estacion inicial
                matriz_ady[pos_i][pos_j] = diferencia_i_a_j;
            } // Actualizo la matriz ya que puedo quedarme ahi.
            if(!es_estacion_primera[pos_j])  {                // A menos que sea estacion incial
                matriz_ady[pos_j][pos_i] = diferencia_j_a_i; // Actualizo ya que puedo pasar el dia.
			}
        }
    }

    /** Calculo el camino minimo entre todo par de nodos **/
    forn(k, cantidad_nodos) forn(i, cantidad_nodos) forn(j, cantidad_nodos)
        matriz_ady[i][j] = min ( matriz_ady[i][j], matriz_ady[i][k]+matriz_ady[k][j] );

    /** Calculo todas las formas de ir de uno a otro **/
    int tiempo_anterior = -1;
    respuestas las_respuestas;

    forall(d, los_nodos){
        if(d->second == desde){
            if(tiempo_anterior != d->first){
                int minimo = infinito;
                forall(h, los_nodos){
                    if(h->second == hasta){
                        int p_x = las_posiciones[nodo(d->first, d->second)];
                        int p_y = las_posiciones[nodo(h->first, h->second)];
                        int tiempo_llegada = matriz_ady[p_x][p_y];
                        if(minimo > tiempo_llegada){
                            minimo = tiempo_llegada;
                        }
                    }
                }
                if(minimo < infinito){
                    tiempo_anterior = d->first;
                    las_respuestas.push_back(respuesta(((d->first)%un_dia), minimo));
                }
            }
        }
    }

    /** Obtengo dentro de todas las posibilidades las validas **/
    respuestas las_respuestas_invalidas;
    forallDist(i, j, las_respuestas){
        if  ( i->first < j->first && (i->first + i->second) >= (j->first + j->second)){
            las_respuestas_invalidas.push_back(respuesta(i->first, i->second));
        }

        if  (j->first < i->first && (j->first + j->second) >= (i->first + i->second)) {
            las_respuestas_invalidas.push_back(respuesta(j->first, j->second));
        }

        if  (i->first < j->first + un_dia && (i->first + i->second) >= (j->first + j->second) + un_dia){
            las_respuestas_invalidas.push_back(respuesta(i->first, i->second));
        }

        if  (j->first < i->first + un_dia && (j->first + j->second) >= (i->first + i->second) + un_dia){
            las_respuestas_invalidas.push_back(respuesta(j->first, j->second));
        }
    }
    
    /** Muestro los resultados validos **/
    forall(i, las_respuestas) {
        bool esta = false;
        forall(j, las_respuestas_invalidas){
            if(j->first == i->first && j->second == i->second){
                esta = true;
                break;
            }
        }
        if(!esta){
            cout << tiempoFormated(i->first) <<" " << tiempoNoFormated(i->second) << endl;
        }
    }
}

int main(){
    int numero_test_case = 0;
    string fin = "";
    cin >> numero_test_case;
    forn(kk, numero_test_case) {
        cout << fin;
        ResolverUnCaso();
        fin = "\n";
    }
    return 0;
}
